package kz.pompei.OneGwt.ifaces.util;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.i18n.client.constants.TimeZoneConstants;
import com.google.gwt.i18n.shared.TimeZone;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.UIObject;

public class ClientUtil {
  public final static DateTimeFormat DMY = DateTimeFormat.getFormat( "dd/MM/yyyy" );
  public final static DateTimeFormat DMY_HMS = DateTimeFormat.getFormat( "dd/MM/yyyy HH:mm:ss" );
  public final static DateTimeFormat DMY_HM = DateTimeFormat.getFormat( "dd/MM/yyyy HH:mm" );
  public final static DateTimeFormat YMD_HMS = DateTimeFormat.getFormat( "yyyy-MM-dd HH:mm:ss" );
  public final static DateTimeFormat YMD = DateTimeFormat.getFormat( "yyyy-MM-dd" );
  public final static DateTimeFormat YMD_HMSS = DateTimeFormat
      .getFormat( "yyyy-MM-dd HH:mm:ss.SSS" );
  public final static DateTimeFormat HMS = DateTimeFormat.getFormat( "HH:mm:ss" );
  public final static DateTimeFormat HM = DateTimeFormat.getFormat( "HH:mm" );
  public final static DateTimeFormat MM = DateTimeFormat.getFormat( "MM" );
  public final static DateTimeFormat YYYY = DateTimeFormat.getFormat( "yyyy" );
  public final static DateTimeFormat YYYY_MM = DateTimeFormat.getFormat( "yyyy-MM" );
  
  public final static TimeZoneConstants timeZoneData = GWT.create( TimeZoneConstants.class );
  public final static String strTimeZone = timeZoneData.asiaAlmaty();
  public final static TimeZone timeZone = com.google.gwt.i18n.client.TimeZone
      .createTimeZone( strTimeZone );
  
  public static final Object month[][] = new Object[][] { { "Январь", 31 }, { "Февраль", 28 },
      { "Март", 31 }, { "Апрель", 30 }, { "Май", 31 }, { "Июнь", 30 }, { "Июль", 31 },
      { "Август", 31 }, { "Сентябрь", 30 }, { "Октябрь", 31 }, { "Ноябрь", 30 }, { "Декабрь", 31 } };
  public static final String day_of_week[] = new String[] { "ВС", "ПН", "ВТ", "СР", "ЧТ", "ПТ",
      "СБ", };
  
  public static String toDMY(Date date) {
    return toDMY( date, "" );
  }
  
  public static String toDMY_HMS(Date date) {
    return toDMY_HMS( date, "" );
  }
  
  public static String toDMY_HM(Date date) {
    return toDMY_HM( date, "" );
  }
  
  public static String toDMY_HM(Date date, String onNull) {
    if (date == null) return onNull;
    return DMY_HM.format( date, timeZone );
  }
  
  public static String toDMY(Date date, String onNull) {
    if (date == null) return onNull;
    return DMY.format( date, timeZone );
  }
  
  public static String toYMD(Date date) {
    if (date == null) return "";
    return YMD.format( date, timeZone );
  }
  
  public static String toMM(Date date) {
    if (date == null) return "";
    return MM.format( date, timeZone );
  }
  
  public static String toYYYY(Date date) {
    if (date == null) return "";
    return YYYY.format( date, timeZone );
  }
  
  public static String toDMY_HMS(Date date, String onNull) {
    if (date == null) return onNull;
    return DMY_HMS.format( date, timeZone );
  }
  
  public static String toHMS(Date date) {
    return toHMS( date, "" );
  }
  
  public static String toHMS(Date date, String onNull) {
    if (date == null) return onNull;
    return HMS.format( date );
  }
  
  public static String toYMD_HMS(Date date) {
    return toYMD_HMS( date, "-" );
  }
  
  public static String toYMD_HMS(Date date, String defaultValue) {
    if (date == null) return defaultValue;
    return YMD_HMS.format( date, timeZone );
  }
  
  public static String toYM(Date date) {
    return YYYY_MM.format( date, timeZone );
  }
  
  /**
   * Безопасное на <code>null</code> сравнение дат
   * 
   * @param d1
   *          исходная дата 1
   * @param d2
   *          исходнач дата 2
   * @return сравнительная характеристика исходных дат
   */
  public static int compare(Date d1, Date d2) {
    if (d1 == null) {
      if (d2 == null) return 0;
      return -1;
    }
    if (d2 == null) {
      return 1;
    }
    return d1.compareTo( d2 );
  }
  
  public static boolean debug = true;
  
  /**
   * Оборачивает в ХТМЛ, который придаёт тексту стиль ссылки
   * 
   * @param text
   *          исходный текст
   * @return обёрнутый текст
   */
  public static String wrapWithLinkStyleHtml(String text) {
    return "<span " + " style=\"text-decoration: underline;" + " color: #486b70;\">" + text
        + "</span>";
  }
  
  public static final NumberFormat NUMBER_FORMAT = NumberFormat.getFormat( "#,##0.00" );
  
  /**
   * Преобразует BigDecimal в строковое представление пригодное для просмотра
   * пользователем
   * 
   * @param value
   *          исходное значение
   * @param onNull
   *          возвращаемое значение в случае, если <code>value == null</code>
   * @return преобразованное значение или <code>onNull</code>, если
   *         <code>value == null</code>
   */
  public static String bdToStr(BigDecimal value, String onNull) {
    if (value == null) return onNull;
    return NUMBER_FORMAT.format( value.doubleValue() );
  }
  
  /**
   * Преобразует Double в строковое представление пригодное для просмотра
   * пользователем
   * 
   * @param value
   *          исходное значение
   * @param onNull
   *          возвращаемое значение в случае, если <code>value == null</code>
   * @return преобразованное значение или <code>onNull</code>, если
   *         <code>value == null</code>
   */
  public static String doubleToStr(Double value, String onNull) {
    if (value == null) return onNull;
    return NUMBER_FORMAT.format( value.doubleValue() );
  }
  
  /**
   * Преобразует BigDecimal в строковое представление пригодное для просмотра
   * пользователем
   * 
   * @param value
   *          исходное значение
   * @return преобразованное значение, или <code>""</code>, если
   *         <code>value == null</code>
   */
  public static String bdToStr(BigDecimal value) {
    return bdToStr( value, "" );
  }
  
  public static int rnd(int top) {
    int i = Random.nextInt();
    if (i < 0) i = -i;
    return i % top;
  }
  
  public static <T> T getRndElem(List<T> lst) {
    if (lst.size() == 0) return null;
    int rndIndex = rnd( lst.size() );
    System.out.println( "getRndElem: " + rndIndex + " from " + lst.size() );
    return lst.get( rndIndex );
  }
  
  public static <T> T getRndElem(T[] array) {
    if (array.length == 0) return null;
    return array[rnd( array.length )];
  }
  
  /**
   * Анализирует строку для преобразования её в хэш. Строка должна быть
   * разделена запятыми на пары ключ-значение. Ключ и значение в этих парах
   * разделены двоеточием
   * 
   * @param str
   *          исходная строка
   * @return результирующий хэш
   */
  public static Map<String, String> parseToMap(String str) {
    Map<String, String> ret = new HashMap<String, String>();
    for (String arg : str.split( "\\s*,\\s*" )) {
      int commaIndex = arg.indexOf( ':' );
      if (commaIndex < 0) {
        ret.put( arg, null );
      } else {
        String key = arg.substring( 0, commaIndex );
        String value = arg.substring( commaIndex + 1 );
        ret.put( key.trim(), value.trim() );
      }
    }
    return ret;
  }
  
  public native static void windowOpen(String htmlText) /*-{
		var doc = $wnd.open();
		doc.document.write(htmlText);
		doc.document.close();
  }-*/;
  
  public static native String getUrlParam(String strParamName) /*-{
		var strReturn = "";
		var strHref = $wnd.location.href;
		if (strHref.indexOf("?") > -1) {
			var strQueryString = strHref.substr(strHref.indexOf("?"))
					.toLowerCase();
			var aQueryString = strQueryString.split("&");
			for ( var iParam = 0; iParam < aQueryString.length; iParam++) {
				if (aQueryString[iParam].indexOf(strParamName + "=") > -1) {
					var aParam = aQueryString[iParam].split("=");
					strReturn = aParam[1];
					break;
				}
			}
		}
		return strReturn;
  }-*/;
  
  public static void exit() {
    gotoURL( "../j_spring_security_logout" );
  }
  
  public static native void gotoURL(String url) /*-{
		$wnd.document.location.href = url;
  }-*/;
  
  public static native String getLocationHref() /*-{
		return $wnd.document.location.href;
  }-*/;
  
  public static native void setShortcutIcon(String url) /*-{
		var link = document.createElement('link');
		link.rel = 'shortcut icon';
		link.href = url;
		$wnd.document.getElementsByTagName('head')[0].appendChild(link);
  }-*/;
  
  public static native void sendToCti(String url)/*-{
		$wnd.js_sendToCti(url);
  }-*/;
  
  public static native String escape(String str)/*-{
		return escape(str);
  }-*/;
  
  public static native String unescape(String str)/*-{
		return unescape(str);
  }-*/;
  
  public static String getAppName() {
    String url = GWT.getModuleBaseURL();
    {
      int idx = url.indexOf( "://" );
      if (idx > -1) {
        url = url.substring( idx + 3 );
      }
    }
    {
      int idx = url.indexOf( "/" );
      if (idx > -1) {
        url = url.substring( idx + 1 );
      }
    }
    {
      int idx = url.indexOf( "/" );
      if (idx > -1) {
        url = url.substring( 0, idx );
      }
    }
    return url;
  }
  
  private static final Date EXPIRES_SIZE_COOKES = new Date( System.currentTimeMillis()
      + (1000L * 60L * 60L * 24L * 365L * 10L/* через 10 лет */) );
  
  public static Date parseDateTimeISO(String date) {
    return date == null ? null :YMD_HMS.parse( date );
  }
  
  public static Date parseDateTimeYYYY_MM(String date) {
    return date == null ? null :YYYY_MM.parse( date );
  }
  
  public static boolean isCorrectDate(String date, DateTimeFormat format) {
    try {
      format.parse( date );
      return true;
    } catch (Exception e) {
      return false;
    }
  }
  
  /**
   * Размещает объект locating относительно объекта relativeBy по центру
   * 
   * @param locating
   *          размещаемый объект
   * @param relativeBy
   *          объект, относительно которого происходит размещение
   */
  public static void locateByCenter(PopupPanel locating, UIObject relativeBy) {
    int relativeCenterLeft = (relativeBy.getAbsoluteLeft() + relativeBy.getOffsetWidth()) >> 1;
    int relativeCenterTop = (relativeBy.getAbsoluteTop() + relativeBy.getOffsetHeight()) >> 1;
    
    int locatingLeft = relativeCenterLeft - (locating.getOffsetWidth() >> 1);
    int locatingTop = relativeCenterTop - (locating.getOffsetHeight() >> 1);
    
    if (locatingLeft < 0) locatingLeft = 0;
    if (locatingTop < 0) locatingTop = 0;
    
    locating.setPopupPosition( locatingLeft, locatingTop );
  }
}
